/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.ambimmort.ucagent.modules.server.codec;

import com.ambimmort.ucagent.utils.HexUtil;
import com.ambimmort.umessage.UcType;
import net.sf.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author 定巍
 */
public class UcRawMessage {

    public static int HEADER_LENGTH = 18;

    private long id;
    private byte[] header = new byte[HEADER_LENGTH];
    private byte[] body = null;
    private String sessionId;
    private boolean manaul = false;

    private Object arg = null;

    private Object log = null;

    public UcRawMessage() {
        header[0] = (byte) 0x10;
        header[1] = (byte) 0x43;
        header[2] = (byte) 0x55;
        header[3] = (byte) 0x43;
    }

    public UcRawMessage(byte[] data) {
        if (data == null | data.length < HEADER_LENGTH) {
            throw new RuntimeException("UcRawMessage Construction Exception:");
        }
        System.arraycopy(data, 0, header, 0, HEADER_LENGTH);
        body = new byte[data.length - HEADER_LENGTH];
        System.arraycopy(data, HEADER_LENGTH, body, 0, data.length - HEADER_LENGTH);
    }

    public String getSessionId() {
        return sessionId;
    }

    public void setSessionId(String sessionId) {
        this.sessionId = sessionId;
    }

    public Object getArg() {
        return arg;
    }

    public void setArg(Object arg) {
        this.arg = arg;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public Object getLog() {
        return log;
    }

    public void setLog(Object log) {
        this.log = log;
    }

    public boolean isManaul() {
        return manaul;
    }

    public void setManaul(boolean manaul) {
        this.manaul = manaul;
    }

    public void normalize() {
    }

    public byte getVersion() {
        return header[0];
    }

    public String getProtoSignature() {
        byte[] d = new byte[3];
        d[0] = header[1];
        d[1] = header[2];
        d[2] = header[3];
        return new String(d);
    }

    public byte[] getHeader() {
        return header;
    }

    public UcType.UINT4 getMessageLength() {
        return new UcType.UINT4(new byte[]{header[14], header[15], header[16], header[17]});
    }

    public void setMessageLength(UcType.UINT4 length) {
        byte[] lbyte = length.getBytes();
        header[14] = lbyte[0];
        header[15] = lbyte[1];
        header[16] = lbyte[2];
        header[17] = lbyte[3];
    }

    public UcType.UINT4 getMessageSequenceNo() {
        return new UcType.UINT4(new byte[]{header[10], header[11], header[12], header[13]});
    }

    public void setMessageSequenceNo(UcType.UINT4 messageSequenceNo) {
        byte[] msnByte = messageSequenceNo.getBytes();
        header[10] = msnByte[0];
        header[11] = msnByte[1];
        header[12] = msnByte[2];
        header[13] = msnByte[3];
    }

    public UcType.UINT1 getMessageType() {
        return new UcType.UINT1(new byte[]{header[4]});
    }

    public void setMessageType(UcType.UINT1 messageType) {
        header[4] = messageType.toByte();
    }

    public UcType.UINT4 getMessageNo() {
        return new UcType.UINT4(new byte[]{header[5], header[6], header[7], header[8]});
    }

    public void setMessageNo(UcType.UINT4 messageNo) {
        byte[] mnbytes = messageNo.getBytes();
        header[5] = mnbytes[0];
        header[6] = mnbytes[1];
        header[7] = mnbytes[2];
        header[8] = mnbytes[3];
    }

    public long getLengthNeeded() {
        return getMessageLength().toLong() - HEADER_LENGTH;
    }

    public void setHeader(byte[] header) {
        this.header = header;
    }

    public byte[] getBody() {
        return body;
    }

    public void setBody(byte[] body) {
        this.body = body;
    }

    public byte[] getBytes() {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            os.write(header);
            os.write(body);
        } catch (IOException ex) {
            Logger.getLogger(UcRawMessage.class.getName()).log(Level.SEVERE, null, ex);
        }

        return os.toByteArray();
    }

    public ByteBuffer getByteBuffer() {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            os.write(header);
            os.write(body);
        } catch (IOException ex) {
            Logger.getLogger(UcRawMessage.class.getName()).log(Level.SEVERE, null, ex);
        }

        return ByteBuffer.wrap(os.toByteArray());
    }

    @Override
    public String toString() {

        JSONObject obj = new JSONObject();
//        obj.put("ml", this.getMessageLength().toLong());
//        obj.put("mt", HexUtil.getHex(this.getMessageType().toByte()));
//        obj.put("mn", this.getMessageNo().toInteger());
//        obj.put("msn", this.getMessageSequenceNo().toLong());

        obj.put("MessageLength", this.getMessageLength().toLong());
        obj.put("MessageType", HexUtil.getHex(this.getMessageType().toByte()));
        obj.put("MessageNo", this.getMessageNo().toInteger());
        obj.put("MessageSerialNo", this.getMessageSequenceNo().toLong());

        return "\n"+obj.toString(4);
    }

}
